package com.sunlee.common.core.enums;

import java.text.MessageFormat;
import java.util.Arrays;

/**
 * API 统一返回异常状态码
 *
 * @author sunlee
 */
public enum ErrorCodeEnum {

    /**
     * 常用异常
     */
    SUCCESS(0, "success"),
    SERVER_INTERNAL_ERROR(500, "系统繁忙，请稍后重试"),
    UNAUTHORIZED(401, "请登录后再操作！"),

    /* 参数错误：10001-19999 */
    PARAM_IS_INVALID(10001, "参数:{0}值无效"),
    PARAM_IS_BLANK(10002, "参数:{0}值为空"),
    PARAM_TYPE_BIND_ERROR(10003, "参数:{0}值类型错误"),
    PARAM_NOT_COMPLETE(10004, "缺失必要参数"),

    /* 用户错误：20001-29999*/
    PARAMETER_ERROR(20001, "参数错误[{0}]"),
    USER_NOT_LOGGED_IN(20002, "用户未登录"),
    USER_PASSWORD_WRONG(20003, "密码错误"),
    USER_ACCOUNT_FORBIDDEN(20004, "账号已被禁用"),
    USER_NOT_EXIST(20005, "用户不存在"),
    USER_LOGGED_FAIL(20006, "登录失败 {0}"),
    INVALID_SYMBOL(20007, "包含非法字符"),
    TOKEN_INVALID(20008, "登录已过期，请重新登录"),
    USER_LOCKED(20009, "账号已被锁定"),
    SUPERIOR_DEPT_ERROR(20010, "上级部门选择错误"),
    DEPT_SUB_DELETE_ERROR(20011, "请先删除下级部门"),
    DEPT_USER_DELETE_ERROR(20012, "请先删除部门下的用户"),
    TOKEN_GEN_FAIL(20013, "令牌创建失败"),
    SUPERIOR_MENU_ERROR(20014, "上级菜单不能为自身"),
    CAPTCHA_ERROR(20015, "验证码错误"),
    IDENTIFIER_NOT_NULL(20016, "唯一标识不能为空"),
    DATA_SCOPE_PARAMS_ERROR(20017, "数据权限接口，只能是Map类型参数"),
    UPLOAD_FILE_EMPTY(20018, "请上传文件"),
    RESOURCE_DOWNLOAD_ONLY_ONCE(20019, "相同资源只可下载一次"),
    USER_ACCOUNT_DISABLED(20020, "账号已被禁用，请联系管理员"),

    /* 业务错误：30001-39999 */
    EXCEL_OPERATE_FAIL(30001, "Excel操作失败"),
    EXCEL_EXPORT_FAIL(30002, "Excel导出失败"),
    SUB_MENU_EXIST(30003, "先删除子菜单或按钮"),
    TOKEN_NOT_EMPTY(30004, "token不能为空"),
    STORAGE_INFO_NOT_CONFIG(30005, "未配置存储信息"),
    SUB_CATEGORY_EXIST(30006, "[{0}] 存在子分类，请先删除"),
    MISSING_CATEGORY_ID(30007, "缺少分类ID"),
    RESOURCE_NOT_FOUND(30008, "找不到该资源的下载地址"),
    RESOURCE_DOWNLOAD_FAILED(30009, "资源下载失败"),
    RESOURCES_REMOVED(30010, "该资源已下架"),
    MISSING_PRODUCT_ID(30011, "缺少资源ID"),

    /* 系统错误：40001-49999 */
    STREAM_CLOSE_EXCEPTION(40001, "数据流关闭异常"),
    JOB_ERROR(40002, "定时任务失败"),
    JOB_GET_CRON_ERROR(40003, "获取cron表达式失败"),
    JOB_CREATE_ERROR(40004, "创建定时任务失败"),
    JOB_UPDATE_ERROR(40005, "创建定时任务失败"),
    JOB_RUN_ERROR(40006, "执行定时任务失败"),
    JOB_PAUSE_ERROR(40007, "暂停定时任务失败"),
    JOB_RESUME_ERROR(40008, "恢复定时任务失败"),
    JOB_DELETE_ERROR(40009, "删除定时任务失败"),
    PARAMS_GET_ERROR(400010, "获取参数失败"),
    OSS_UPLOAD_FILE_ERROR(400011, "上传文件失败{0}"),

    /* 数据错误：50001-599999 */
    RESULT_DATA_NONE(50001, "数据未找到"),
    DATA_IS_WRONG(50002, "数据有误:{0}"),
    DATA_ALREADY_EXISTED(50003, "数据\"{0}\"已存在"),
    MODIFY_DATA_NOT_EXISTED(50004, "修改的数据不存在,id:{0}"),
    SAVE_WRONG(50005, "保存{0}出错 {1}"),
    UPDATE_WRONG(50006, "更新{0}失败 {1}"),
    DELETE_WRONG(50007, "删除{0}失败"),
    DATA_ALREADY_EXISTED_NO_PARAM(50008, "已存在数据"),
    REDIS_INCR_MUST_MORE_ZERO(50009, "key:{0}的递增因子必须大于0"),
    ENTITY_TO_JSON_ERROR(500010, "实体转Json异常"),
    EXIST_DATA_DELETE_ERROR(500011, "存在关联数据，不允许直接删除"),

    /* 接口错误：60001-69999 */
    INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口{0}调用异常"),
    INTERFACE_OUTER_INVOKE_ERROR(60002, "外部系统接口{0}调用异常"),
    INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
    INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
    INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
    INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),
    INTERFACE_FORBID_IN_CURRENT_ENV(60007, "当前环境:{0} 禁止使用该接口"),

    ;

    private Integer code;
    private String msg;
    private String template;

    ErrorCodeEnum(int code, String template) {
        this.code = code;
        this.msg = template;
        this.template = template;
    }

    public String getMsg() {
        return msg;
    }

    public int getCode() {
        return code;
    }

    public static ErrorCodeEnum valueOfCode(int code) {
        return Arrays.stream(ErrorCodeEnum.values())
                .filter(t -> t.code == code)
                .findFirst()
                .orElse(SERVER_INTERNAL_ERROR);
    }


    public static String msgOfCode(int code) {
        for (ErrorCodeEnum userType : values()) {
            if (userType.getCode() == code) {
                return userType.getMsg();
            }
        }
        return SERVER_INTERNAL_ERROR.getMsg();
    }

    public ErrorCodeEnum format(Object... msgArgs) {
        this.msg = MessageFormat.format(template, msgArgs);
        return this;
    }
}
